﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using System.IO;
using System.Reflection;
using Skynet.CommonLibrary.Extension;
using Skynet.CommonLibrary.ThreadRefreshTime.Interface;
using Skynet.CommonLibrary.ThreadRefreshTime.RefreshElement;
using Skynet.CommonLibrary.ThreadRefreshTime.StrateGy;

namespace Skynet.CommonLibrary.ThreadRefreshTime
{
    /// <summary>
    /// 线程刷新管理（通过XML）
    /// </summary>
    ///<remarks>
    /// 作者：         李志强
    /// 开发时间：  2011-05-16
    /// </remarks>
    internal class ThreadRefreshXmlManage : ThreadRefreshManage, IRefreshTimeXmlManage
    {
        public string RefreshTaskToXml(RefreshTaskXmlElement taskTimer)
        {
            XDocument document = new XDocument();

            XElement root = new XElement("root");
            //root.Add(new XElement("RefreshMnaage",
            //                 new XElement("RefreshInterval", 60000)));
            root.Add(new XElement("RefreshElement",
                new XElement("RefreshInterval", taskTimer.RefreshInterval * 60 * 1000),
                new XElement("RefreshNumber", taskTimer.RefreshNumber),
                new XElement("TaskStartTime", taskTimer.TaskStartTime.ToString("yyyy-MM-dd") == DateTime.MinValue.ToString("yyyy-MM-dd") ? "" : taskTimer.TaskStartTime.ToString("yyyy-MM-dd HH:mm:ss")),
                new XElement("TaskEndTime", taskTimer.TaskEndTime.ToString("yyyy-MM-dd") == DateTime.MinValue.ToString("yyyy-MM-dd") ? "" : taskTimer.TaskEndTime.ToString("yyyy-MM-dd HH:mm:ss")),
                new XElement("TaskConditions",
                    new XAttribute("Month", taskTimer.TaskConditionsMonth ?? ""),
                    new XAttribute("Day", taskTimer.TaskConditionsDay ?? ""),
                    new XAttribute("Hour", taskTimer.TaskConditionsHour ?? ""),
                    new XAttribute("Minute", taskTimer.TaskConditionsMinute ?? ""),
                    new XAttribute("Second", taskTimer.TaskConditionsSecond?? "")),
               new XElement("Description", taskTimer.Description)
                //new XElement("RefreshAction",
                //    new XAttribute("assemblyName", taskTimer.ActionAssableName),
                //    new XAttribute("className", taskTimer.ActionClassNmae),
                //    new XAttribute("methodName", taskTimer.ActionMethodName))
               ));
            root.Add(new XElement("Serategy",
                new XElement("Name",
                    new XAttribute("namespace", "ThreadRefreshTimeLibrary"), taskTimer.Serategy)));

            document.Add(root);
            return              document.ToString();
        }

        /// <summary>
        /// 根据配置文件 添加刷新元素
        /// </summary>
        /// <param name="xmlPath">xml路径</param>
        /// <param name="refreshAction">方法</param>
        /// <returns>任务编号</returns>
        public string AddTask(string xmlPath, Action refreshAction)
        {
            XElement root = XElement.Load(xmlPath);
            return AnsyXml(root, refreshAction);
        }
        public string AddTask(StringReader xml, Action refreshAction)
        {
            XElement root = XElement.Load(xml);
            return AnsyXml(root, refreshAction);
        }

        #region 私有方法
        /// <summary>
        /// 解析XML格式数据
        /// </summary>
        /// <param name="root"></param>
        /// <param name="refreshAction"></param>
        private string AnsyXml(XElement root, Action refreshAction)
        {
            //设置管理器默认定时间隔
            XElement refreshManage = root.Element("RefreshMnaage");
            if (refreshManage != null)
            {
                int interval;
                int.TryParse(refreshManage.Element("RefreshInterval").Value, out interval);
                RefreshInterval = interval == 0 ? 60 * 1000 : interval;
            }
            //设置任务元素
            XElement refreshElement = root.Element("RefreshElement");
            IRefreshTaskTimer rtt = new TaskTimerElement(0);
            //设置元素属性值
            foreach (XElement el in refreshElement.Elements())
            {
                if (el.Name.LocalName == "TaskConditions")
                {
                    GetConditions(el, rtt);
                }
                else
                {
                    PropertyInfo propertyinfo = rtt.GetType().GetProperty(el.Name.LocalName);
                    if (propertyinfo != null)
                    {
                        rtt.SetValue(el.Name.LocalName, el.Value);
                        //propertyinfo.SetTypeValue(rtt, el.Value);
                    }
                }
            }
            rtt.RefreshInterval = rtt.RefreshInterval * 60 * 1000;

            if (refreshAction == null)
                return string.Empty;
            rtt.Refresh = (Action<IRefreshTimer, Exception> failed) =>
            {
                refreshAction();
            };

            //设置执行方式
            XElement serategy = root.Element("Serategy");
            string ass = serategy.Element("Name").Attribute("namespace").Value;
            string className = serategy.Element("Name").Value;
            base.AddRefreshTimer(rtt,
                 System.Reflection.Assembly.Load(ass.Split('.')[0]).CreateInstance(ass + "." + className) as IThreadStrategy);
            return rtt.RefreshID;
        }
        /// <summary>
        /// 任务条件判断
        /// </summary>
        /// <param name="el"></param>
        /// <param name="rtt"></param>
        private void GetConditions(XElement el, IRefreshTaskTimer rtt)
        {
            int[] month = null, day = null, hour = null, second = null, minute = null;
            if (!string.IsNullOrEmpty(el.Attribute("Month").Value))
            {
                month = GetDateConditons(el.Attribute("Month").Value);
            }
            if (!string.IsNullOrEmpty(el.Attribute("Day").Value))
            {
                day =GetDateConditons( el.Attribute("Day").Value);
            }
            if (!string.IsNullOrEmpty(el.Attribute("Hour").Value))
            {
                hour = GetDateConditons(el.Attribute("Hour").Value);
            }
            if (!string.IsNullOrEmpty(el.Attribute("Second").Value))
            {
                second = GetDateConditons(el.Attribute("Second").Value);
            }
            if (!string.IsNullOrEmpty(el.Attribute("Minute").Value))
            {
                minute = GetDateConditons(el.Attribute("Minute").Value);
            }

            if (month == null && day == null && hour == null && second == null && minute == null)
            {
                return;
            }
            else
            {
                rtt.TaskConditions = (DateTime dt) =>
                {
                    //转换成24小时制度
                    DateTime now = DateTime.Parse(dt.ToString("yyyy-MM-dd HH:mm:ss"));
                    bool iscondition = true;
                    if (month != null)
                    {
                        iscondition = iscondition && month.Contains(now.Month);
                    }
                    if (day != null)
                    {
                        iscondition = iscondition && day.Contains(now.Day);
                    }
                    if (hour != null)
                    {
                        iscondition = iscondition && hour.Contains(now.Hour);
                    }
                    if (second != null)
                    {
                        iscondition = iscondition && second.Contains(now.Second);
                    }
                    if (minute != null)
                    {
                        iscondition = iscondition && minute.Contains(now.Minute);
                    }
                    return iscondition;
                };
            }
        }

        //日期指定条件
        private int[] GetDateConditons(string value)
        {
            //判断条件 min-max 情况
            string[] valueItem = value.Split(new char[] { '-' }, StringSplitOptions.RemoveEmptyEntries);
            int min, max;
            List<int> list = new List<int>();
            if (valueItem.Count() == 2)
            {
                int.TryParse(valueItem[0], out min);
                int.TryParse(valueItem[1], out max);
                for (int i = min; i <= max; i++)
                {
                    if (i == 0)
                        continue;
                    list.Add(i);
                }
            }
            if (list.Count > 0)
                return list.ToArray();

            //判断条件 min,min,min……
            valueItem = value.Split(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
            if (valueItem.Count() > 0)
            {
                foreach (string s in valueItem)
                {
                    int.TryParse(s, out min);
                    if (min == 0)
                        continue;
                    list.Add(min);
                }
            }

            if (list.Count > 0)
                return list.ToArray();
            return null;
        }
        #endregion
    }
}
